package com.dc.config.handler;

import com.dc.common.constant.ResultStatus;
import com.dc.common.exception.ServiceException;
import com.dc.common.utils.StringUtil;
import com.dc.common.vo.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @Author zhuangchongyi
 * @Description 全局异常处理类
 * @Date 2020/8/28 17:31
 */
@RestController
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(ShiroException.class)
    public ResultVo shiroException(ShiroException e) {
        log.error("异常信息: ", e);
        if (e instanceof UnknownAccountException) {
            return ResultVo.failed().msg("登录账号不存在");
        } else if (e instanceof IncorrectCredentialsException) {
            return ResultVo.failed().msg("输入密码有误");
        } else if (e instanceof LockedAccountException) {
            return ResultVo.failed().msg("账号已被锁定");
        } else if (e instanceof DisabledAccountException) {
            return ResultVo.failed().msg("登录账号已禁用");
        } else if (e instanceof ExpiredCredentialsException || e instanceof UnauthenticatedException) {
            return ResultVo.failed().code(ResultStatus.NOT_CERTIFIED_CODE.getCode()).msg(ResultStatus.NOT_CERTIFIED_CODE.getMsg());
        } else if (e instanceof UnauthorizedException) {
            return ResultVo.failed().code(ResultStatus.UNAUTHORIZED_CODE.getCode()).msg(ResultStatus.UNAUTHORIZED_CODE.getMsg());
        }
        return ResultVo.failed().code(ResultStatus.ERROR_CODE.getCode()).msg(StringUtil.format("未知系统异常，请稍后重试 {}", e.getMessage()));
    }

    @ExceptionHandler(Exception.class)
    public ResultVo exception(Exception e) {
        log.error("异常信息: ", e);
        return ResultVo.failed().code(ResultStatus.ERROR_CODE.getCode()).msg(StringUtil.format("未知系统异常，请稍后重试{}", e.getMessage()));
    }

    @ExceptionHandler(ServiceException.class)
    public ResultVo serviceException(ServiceException e) {
        log.error("异常信息: ", e);
        return ResultVo.failed().code(e.getCode()).msg(e.getMessage());
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResultVo servletException(HttpRequestMethodNotSupportedException e, HttpServletRequest request) {
        log.error("异常信息: ", e);
        return ResultVo.failed().code(ResultStatus.REQUEST_FAIL_CODE.getCode()).msg(StringUtil.format("{}, {}, {}", ResultStatus.REQUEST_FAIL_CODE.getMsg(), request.getMethod(), request.getServletPath()));
    }


    @ExceptionHandler({BindException.class})
    public ResultVo bindException(BindException e) {
        log.error("异常信息: ", e);
        return ResultVo.failed().msg(Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
    }

    /**
     * 参数不合法异常
     *
     * @param e
     * @return
     * @Description
     * @author
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultVo handleException(MethodArgumentNotValidException e) {
        log.error("异常信息: ", e);
        BindingResult a = e.getBindingResult();
        List<ObjectError> list = a.getAllErrors();
        String errorMsg = "未知异常";
        if (CollectionUtils.isNotEmpty(list)) {
            errorMsg = list.get(0).getDefaultMessage();
        }
        return ResultVo.failed().msg(errorMsg);
    }


    @ExceptionHandler(ValidationException.class)
    public ResultVo validationException(ValidationException e) {
        log.error("异常信息: ", e);
        if (e instanceof ConstraintViolationException) {
            ConstraintViolationException ex = (ConstraintViolationException) e;
            String msg = Arrays.toString(ex.getConstraintViolations().stream().map(ConstraintViolation::getMessage).toArray());
            return ResultVo.failed().msg(msg);
        }
        return ResultVo.failed().msg(e.getMessage());

    }
}
